<?php

abstract class GDGE_Storage_Db_Abstract implements GDGE_Storage_Interface
{
	const ID_FIELD = 'idField';
	const TABLE_NAME = 'tableName';
	const MAX_CAPACITY = 'maxCapacity';
	const MAX_PER_RESOURCE = 'maxPerResource';
	const ALLOW_NEGATIVE = 'allowNegative';

	/**
	 * @var Zend_Db_Adapter_Abstract
	 */
	private $_db;
	private $_valid;
	
	protected $_config = array(
		self::ID_FIELD => 'id',
		self::MAX_CAPACITY => null,
		self::MAX_PER_RESOURCE => null,
		self::ALLOW_NEGATIVE => false,
	);
	
	/**
	 * 
	 * Constructs an abstract storage based on database.
	 *   
	 * @param GDGE_Resource_Validator_Interface $valid valid resources in this storage
	 * @param array $config
	 * @param Zend_Db_Adapter_Abstract $db
	 * @throws GDGE_Storage_Exception
	 */
	public function __construct(GDGE_Resource_Validator_Interface $valid, $config, Zend_Db_Adapter_Abstract $db)
	{
		if ($db == null) {
			$this->_db = Zend_Registry::get('db');
		}
		
		$this->_valid = $valid;
		
		if (is_array($config)) {
			$this->_config = array_merge($this->_config, $config);
		} else {
			throw new GDGE_Storage_Exception('$config must be an array of paramteters', GDGE_Storage_Exception::INVALID_PARAMETER);
		}
		$this->getTableName();
	}
	
	public function getIdField()
	{
		return $this->_config[self::ID_FIELD];
	}
	
	public function getTableName()
	{
		if (!isset($this->_config[self::TABLE_NAME]))
			throw new GDGE_Storage_Exception('Table name is missing from configuration.', GDGE_Storage_Exception::INVALID_PARAMETER);
	}
	public function isValid($resource)
	{
		return $this->_valid->isValid($resource);
	}
	
	/**
	 * @return Zend_Db_Adapter_Abstract
	 */
	protected function db()
	{
		return $this->_db;
	}
	
	public function hasMaxCapacity()
	{
		return $this->_config[self::MAX_CAPACITY] !== null;
	}
	
	public function getMaxCapacity() {
		return $this->_config[self::MAX_CAPACITY];
	}
	
	public function hasMaxPerResource()
	{
		return is_array($this->_config[self::MAX_PER_RESOURCE]);
	}
	
	public function getMax($resource) {
		if (!$this->isValid($resource)) throw new GDGE_Storage_Exception($resource . 'is an invalid resource for this storage', GDGE_Storage_Exception::INVALID_RESOURCE);
		if (!$this->hasMaxPerResource()) throw new GDGE_Storage_Exception('This storage does not have max storage capacity per resource.', GDGE_Storage_Exception::UNSUPPORTED_OPERATION);
		
		return $this->_config[self::MAX_PER_RESOURCE][$resource];
	}
	
	public function hasUnlimitedCapacity()
	{
		return (!$this->hasMaxCapacity() && !$this->hasMaxPerResource());
	}
	
	public function allowNegative()
	{
		return $this->_config[self::ALLOW_NEGATIVE];
	}
}